Add support for PyFrozenDict#6174
Conversation
ee55a45 to
fd12ac9
Compare
|
I am a bit at a loss when it comes to the ffi checks. Pointers welcome |
|
AFAIK the header that contains this in CPython is (Not opining on any part of this patch.) |
|
Thanks I will try that. |
|
So the ffi-check situtation is a bit more complex since accessing the core headers requires Py_BUILD_CORE define. Is this something pyo3 maintainers would be willing to accept ? |
Icxolu
left a comment
There was a problem hiding this comment.
I'm also not an expert on the FFI layer, but here are some comment from my side.
(I haven't looked at the wrapping code, as we first need to get the FFI bindings correct.)
We should not be using any symbols from |
27e8799 to
b3a52c3
Compare
|
|
Icxolu
left a comment
There was a problem hiding this comment.
Thank you, I think we are getting closer. I went through the safe wrapper as well and left some comments below.
|
Thanks for the review. I have been fighthing a bit cfg when it comes to the limited API. I will have to look into your suggestions. |
|
I did a first pass in addressing the review and got clean clippy and test execution locally. The wrapper is now available without the limited API and the cfg are a bit more tiddy. I will check the CI run tomorrow and see if I missed anything else. |
Icxolu
left a comment
There was a problem hiding this comment.
Thank you, some smaller suggestions and some more cfg massaging is needed, but not too much more until we can land this I would say.
4efcac1 to
0373aee
Compare
|
Thanks for the early reviews @Icxolu I think I now have everything in order (including the cfgs). |
Icxolu
left a comment
There was a problem hiding this comment.
Thank you, looking good! Just one small comment regarding the constructor after which I think this is good to go.
| pub fn new<'py, T>(py: Python<'py>, iterable: T) -> PyResult<Bound<'py, PyFrozenDict>> | ||
| where | ||
| T: IntoPyObject<'py>, | ||
| err::PyErr: core::convert::From<<T as conversion::IntoPyObject<'py>>::Error>, |
There was a problem hiding this comment.
Typically the new constructor for similar types takes a Rust iterator. See for example PyFrozenSet or PyTuple. To be consistent I think we should follow that here as well.
I can see that it could be useful to build a PyFrozenDict directly from a Python. The equivalent on dict is called from_sequence, we can use the same here. Similarly we should not make that generic to make users aware that they need to check what they are passing in.
I also saw that for PyFrozenSet we have a PyFrozenSetBuilder. This could be useful for PyFrozenDict as well, out of scope for this PR, but could be a possible followup.
There was a problem hiding this comment.
Let me know if the new verstion looks better.
There was a problem hiding this comment.
I think this is fine for now. Maybe you can leave a TODO that we should look into if the intermediate list is necessary.
I have not seen a from_sequence constructor for when a Python iterable is already available. Do you plan on adding that? I'm also fine if we want to leave it out for now. Just wanted to make sure.
There was a problem hiding this comment.
I though it was not useful but since it was very simple I added it.
|
As a possible followup we can add support for a |
|
I rebased and addressed all review comments. Regarding the constructor, given the limited functionality provided by CPython I went with the safe solution of creating an intermediate Python List. A builder may be feasible following PyFrozenSet but it means mutating frozen object which I am even surprised to see working in the set case. I will try to work in a follow up PR on the PyAnyDict idea this week-end. |
85acaf7 to
07b94bb
Compare
|
ruff is unhappy about some files I did not touch... |
…ro exclusion list
3006d88 to
363cd08
Compare
|
Rebasd on latest main |
|
@bschoenmaeckers Could you elaborate a little on ?
Trying to implement Deref leads into conflict with the PyAny deref and does not match any existing pattern in pyo3 (there is not an AnySet for example). I am willing to work on this but I really not sure how to attack this in way that actually reduces code duplication. |
Maybe introduce a PyAnyDictMethods trait and make PyDictMethods and PyFrozenDictMethod extend it |
|
I can do that but what I am missing is how to avoid duplicating the implementation (since the PyAnyDict_Methods impl block will be identical for PyAnyDict, PyFrozenDict and PyDict). I could use a macro but I am wondering if @bschoenmaeckers had something else in mind. |
|
To go into the #[repr(transparent)]
pub struct PyAnyDict(PyAny);
pyobject_native_type_core!(
PyAnyDict_Check,
...
); // Not sure the macro will work, you might have to implement some traits yourself or with more specialized macros (if it's the case, just read pyobject_native_type_core implementation)
impl PyAnyDictMethods for Bound<'_, PyAnyDict> {
fn ex(&self) {}
}
impl Deref for Bound<'_, PyFrozenDict> {
type Target = Bound<'_, PyAnyDict>;
fn deref(&self) -> &Bound<'_, PyAnyDict> { unsafe { self.cast_unchecked() } }
}But I am not sure if it's actually doable. The trait option would be to have something like the following instead of the impl PyAnyDictMethods for Bound<'_, PyFrozenDict> {
fn ex(&self) { unsafe { self.cast_unchecked::<PyAnyDict>() }.ex() }
} |
I experimented in this commit: 2aa4eb3. I had to remove the DerefToPyAny for PyDict to avoid the conflict. But this is fine as it wil dreef trough the anydict to pyany. If you want you can pick this up and create a mr |
|
Thanks @bschoenmaeckers . Since the commit has what looks like many unrelated changes, I will re-apply the idea in a fresh commit. Should that remaion a follow-up or should I include as part of this PR ? And would a similar PR for AnySet make sense ? |
No description provided.